// notifier/feishu_app.go
package feishu

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"

	// "net/url"
	"strconv"
	"strings"
	"time"
	"v2/config"
	"v2/metrics"
	"v2/model"
)

// FeiShuAppNotifier 飞书应用消息通知器
type FeiShuAppNotifier struct {
	AppID         string
	AppSecret     string
	ReceiveIDType string
	TokenURL      string
	MsgURL        string
	BatchGetIDURL string
}

// NewFeiShuAppNotifier 创建飞书应用通知器
func NewFeiShuAppNotifier(appID, appSecret, receiveIDType string) *FeiShuAppNotifier {
	return &FeiShuAppNotifier{
		AppID:         appID,
		AppSecret:     appSecret,
		ReceiveIDType: receiveIDType,
		TokenURL:      "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
		MsgURL:        "https://open.feishu.cn/open-apis/im/v1/messages",
		BatchGetIDURL: "https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id",
	}
}

// getTenantToken 获取 tenant_access_token
// getTenantToken 获取 tenant_access_token
// getTenantToken 获取 tenant_access_token
func (f *FeiShuAppNotifier) getTenantToken() (string, error) {
	log.Printf("[FeiShu] 开始获取 token, AppID: %s", f.AppID)

	// 确保URL没有多余空格
	f.TokenURL = strings.TrimSpace(f.TokenURL)

	payload := map[string]string{
		"app_id":     strings.TrimSpace(f.AppID),
		"app_secret": strings.TrimSpace(f.AppSecret),
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		log.Printf("[FeiShu] JSON序列化失败: %v", err)
		return "", err
	}

	log.Printf("[FeiShu] 请求数据: %s", string(jsonData))

	// 创建带超时的HTTP客户端
	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	resp, err := client.Post(f.TokenURL, "application/json", bytes.NewReader(jsonData))
	if err != nil {
		log.Printf("[FeiShu] HTTP请求失败: %v", err)
		return "", fmt.Errorf("网络请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	log.Printf("[FeiShu] API响应状态码: %d", resp.StatusCode)
	log.Printf("[FeiShu] API响应: %s", string(body))

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		log.Printf("[FeiShu] 响应解析失败: %v", err)
		return "", fmt.Errorf("响应解析失败: %v", err)
	}

	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		msg, _ := result["msg"].(string)
		if msg == "" {
			msg = "HTTP请求失败"
		}
		log.Printf("[FeiShu] HTTP请求失败: 状态码 %d, 消息 %s", resp.StatusCode, msg)
		return "", fmt.Errorf("HTTP请求失败: 状态码 %d, 消息 %s", resp.StatusCode, msg)
	}

	// ✅ 修复点1：正确处理code字段
	// 飞书API返回的code是float64类型，需要正确断言
	code, codeOk := result["code"].(float64)
	if !codeOk {
		// 尝试其他可能的类型
		if codeInt, ok := result["code"].(int); ok {
			code = float64(codeInt)
			codeOk = true
		} else if codeStr, ok := result["code"].(string); ok {
			if c, err := strconv.ParseFloat(codeStr, 64); err == nil {
				code = c
				codeOk = true
			}
		}
	}

	// ✅ 修复点2：正确判断成功响应
	if codeOk && code != 0 {
		msg, _ := result["msg"].(string)
		log.Printf("[FeiShu] 业务错误: code=%v, msg=%s", code, msg)
		return "", fmt.Errorf("业务错误: code=%v, msg=%s", code, msg)
	}

	// ✅ 修复点3：正确获取token
	token, tokenOk := result["tenant_access_token"].(string)
	if !tokenOk || token == "" {
		// 尝试其他可能的字段名
		if token, ok := result["app_access_token"].(string); ok && token != "" {
			log.Printf("[FeiShu] 使用 app_access_token 代替 tenant_access_token")
			return token, nil
		}

		log.Printf("[FeiShu] 响应中缺少有效的 tenant_access_token")
		return "", fmt.Errorf("响应中缺少有效的 tenant_access_token")
	}

	log.Printf("[FeiShu] 成功获取 token")
	return token, nil
}

func (f *FeiShuAppNotifier) GetUserIDByMobile(token, mobile string) (string, error) {
	// 格式化手机号（添加国家代码）
	if !strings.HasPrefix(mobile, "+") {
		mobile = "+86 " + mobile
	}

	// 确保手机号格式正确（+86 后面有空格）
	if strings.HasPrefix(mobile, "+86") && !strings.HasPrefix(mobile, "+86 ") {
		mobile = "+86 " + strings.TrimPrefix(mobile, "+86")
	}

	log.Printf("[FeiShu] 正在查询手机号: %s", mobile)

	// 构建请求体
	requestBody := map[string]interface{}{
		"mobiles":          []string{mobile},
		"user_id_type":     f.ReceiveIDType,
		"include_resigned": false,
	}

	jsonData, err := json.Marshal(requestBody)
	if err != nil {
		return "", err
	}

	// 创建POST请求
	req, err := http.NewRequest("POST", f.BatchGetIDURL, bytes.NewReader(jsonData))
	if err != nil {
		return "", err
	}

	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json; charset=utf-8")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	log.Printf("[FeiShu] API响应: %s", string(body))

	var result map[string]interface{}
	if err := json.Unmarshal(body, &result); err != nil {
		return "", err
	}

	// 修改点1：只有当code存在且不等于0时才返回错误
	if code, ok := result["code"].(float64); ok && code != 0 {
		msg := "未知错误"
		if m, ok := result["msg"].(string); ok {
			msg = m
		}
		return "", fmt.Errorf("获取用户ID失败: %s", msg)
	}

	// 修改点2：更健壮地解析响应
	data, ok := result["data"].(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("解析用户数据失败: 无效的数据格式")
	}

	items, ok := data["user_list"].([]interface{})
	if !ok || len(items) == 0 {
		return "", fmt.Errorf("未找到有效的用户ID")
	}

	// 获取第一个用户的信息
	userInfo, ok := items[0].(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("解析用户信息失败")
	}

	// 获取用户ID
	userID, ok := userInfo["user_id"].(string)
	if !ok {
		return "", fmt.Errorf("获取用户ID失败: 用户ID字段不存在或类型错误")
	}

	return userID, nil
}

// GetUserIDByPhoneNumbers 通过配置的手机号列表获取所有用户ID
func (f *FeiShuAppNotifier) GetUserIDByPhoneNumbers(token string) ([]string, error) {
	cfg := config.Global.Notifier.FeiShuApp
	var userIds []string

	for _, mobile := range cfg.PhoneNumbers {
		log.Printf("[FeiShu] 正在处理手机号: %s", mobile)

		// 格式化手机号
		formattedMobile := mobile
		if !strings.HasPrefix(mobile, "+") {
			formattedMobile = "+86 " + mobile
		}

		log.Printf("[FeiShu] 格式化后的手机号: %s", formattedMobile)

		// 获取用户ID
		userID, err := f.GetUserIDByMobile(token, formattedMobile)
		if err != nil {
			log.Printf("[FeiShu] 获取手机号 %s 的用户ID失败: %v", formattedMobile, err)
			continue
		}

		log.Printf("[FeiShu] 手机号 %s 对应的用户ID: %s", formattedMobile, userID)
		userIds = append(userIds, userID)
	}

	return userIds, nil
}

// sendToUser 发送消息给单个用户
func (f *FeiShuAppNotifier) sendToUser(token, receiveID, content string) error {
	// 1. 先创建消息内容对象
	messageContent := map[string]string{
		"text": content,
	}

	// 2. 将消息内容序列化为JSON字符串
	contentJSON, err := json.Marshal(messageContent)
	if err != nil {
		return fmt.Errorf("消息内容序列化失败: %v", err)
	}

	// 3. 构造请求体
	payload := map[string]interface{}{
		"receive_id": receiveID,
		"content":    string(contentJSON), // 注意：这里已经是JSON字符串
		"msg_type":   "text",
	}

	// 4. 序列化整个payload
	jsonData, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("请求体序列化失败: %v", err)
	}

	// 5. 创建请求
	url := fmt.Sprintf("%s?receive_id_type=%s", f.MsgURL, f.ReceiveIDType)
	req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
	if err != nil {
		return fmt.Errorf("创建请求失败: %v", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("发送请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result map[string]interface{}
	json.Unmarshal(body, &result)

	// 6. 检查响应
	var code float64
	if codeVal, ok := result["code"]; ok {
		switch v := codeVal.(type) {
		case float64:
			code = v
		case int:
			code = float64(v)
		case string:
			if c, err := strconv.ParseFloat(v, 64); err == nil {
				code = c
			}
		}
	}

	if code != 0 {
		msg, _ := result["msg"].(string)
		return fmt.Errorf("发送消息失败: %s", msg)
	}

	return nil
}

// Send 发送应用消息
func (f *FeiShuAppNotifier) Send(alert model.AlertInfo) error {
	// start := time.Now()

	// 1. 获取 tenant_access_token
	token, err := f.getTenantToken()
	if err != nil {
		log.Printf("[FeiShuApp] 获取 token 失败: %v", err)
		metrics.AlertSentCounter.WithLabelValues("feishu_app", "failure").Inc()
		return err
	}

	// 2. 通过手机号获取用户ID列表
	userIDs, err := f.GetUserIDByPhoneNumbers(token)
	if err != nil {
		log.Printf("[FeiShuApp] 通过手机号获取用户ID失败: %v", err)
		metrics.AlertSentCounter.WithLabelValues("feishu_app", "failure").Inc()
		return err
	}

	// 如果没有获取到用户ID，直接返回
	if len(userIDs) == 0 {
		log.Printf("[FeiShuApp] 没有有效的用户ID，跳过发送")
		return nil
	}

	// 3. 构造消息内容
	content := fmt.Sprintf(
		"%s %s\n\n"+
			"📌 **告警名称**: %s\n"+
			"📍 **所属集群**: %s\n"+
			"🔔 **告警级别**: %s\n"+
			"🕒 **触发时间**: %s\n"+
			"📊 **当前值**: %s\n"+
			"👥 **告警分组**: %s",
		alert.EmojiPrefix(),
		"告警",
		alert.RuleName,
		alert.Cluster,
		alert.SeverityText,
		alert.FormattedTime,
		alert.TriggerValue,
		alert.GroupName,
	)

	for k, v := range alert.TagsMap {
		content += fmt.Sprintf("\n🏷️ `%s`: `%s`", k, v)
	}

	// 4. 遍历所有用户ID，发送消息
	var successCount, failureCount int
	for _, userID := range userIDs {
		err := f.sendToUser(token, userID, content)
		if err != nil {
			// 检查是否是用户未关注错误
			if strings.Contains(err.Error(), "92500") {
				log.Printf("[FeiShuApp] 用户 %s 未关注应用", userID)
				failureCount++
			} else {
				log.Printf("[FeiShuApp] 发送给用户 %s 失败: %v", userID, err)
				failureCount++
			}
		} else {
			successCount++
		}
	}

	// 5. 更新指标
	total := len(userIDs)
	metrics.AlertSentCounter.WithLabelValues("feishu_app", "success").Add(float64(successCount))
	metrics.AlertSentCounter.WithLabelValues("feishu_app", "failure").Add(float64(failureCount))
	// metrics.AlertSendDuration.WithLabelValues("feishu_app").Observe(time.Since(start).Seconds())

	log.Printf("[FeiShuApp] 已发送: %s, 成功: %d/%d", alert.RuleName, successCount, total)
	return nil
}
